package coalition.formation;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.List;


import coalition.formation.coalitions.Core;
import coalition.formation.coalitions.MergeProof;
import coalition.formation.coalitions.NoTreat;
import coalition.formation.coalitions.SplitProof;
import coalition.formation.externality.Externality;
import coalition.formation.parse.PartitionParser;
import coalition.formation.parse.PartitionPlusExternalities;
import coalition.formation.partitions.Partition;
import coalition.formation.partitions.PartitionDecorator;


public class AltruismFromFile implements Externality{
	
	HashMap<String, float[]> externalities = new HashMap<String, float[]>();
	
	int numAgents;
	
	public static void main(String[] args) {
		String file = "./inputs/instance.txt";
		if(args.length != 0 && args[0] != null){
			System.out.println("using command line specified input file: " + args[0]);
			file = args[0];
		}
		AltruismFromFile altruismFixture = new AltruismFromFile(file);
		
		System.out.println("Core partitions");
		
		Core core = new Core(altruismFixture);
		List<int[]> corePartitions = core.getCore();
		for(int[] partition : corePartitions){
			System.out.println(Partition.partitionToExpandedString(partition));
		}
		
		System.out.println("________________________________________________________");
		System.out.println("Split-proof partitions");
		
		SplitProof splitProof = new SplitProof(altruismFixture);
		List<int[]> splitProofPartitions = splitProof.getSplitProofPartitions();
		for(int[] partition : splitProofPartitions){
			System.out.println(Partition.partitionToExpandedString(partition));
		}		
		System.out.println("________________________________________________________");
		System.out.println("Merge-proof partitions");
		
		MergeProof mergeProof = new MergeProof(altruismFixture);
		List<int[]> mergeProofPartitions = mergeProof.getMergeProofPartitions();
		for(int[] partition : mergeProofPartitions){
			System.out.println(Partition.partitionToExpandedString(partition));
		}			
		
		System.out.println("________________________________________________________");
		System.out.println("No-treat partitions");
		
		NoTreat noTreat = new NoTreat(altruismFixture);
		List<int[]> noTreatPartitions = noTreat.getNoTreatPartitions();
		for(int[] partition : noTreatPartitions){
			System.out.println(Partition.partitionToExpandedString(partition));
		}			
		
		//Recap:
		System.out.println("Review:");
		System.out.println("Core:");
		for(int[] partition : corePartitions){
			System.out.println(Partition.partitionToExpandedString(partition));
		}	
		System.out.println("Split-proof:");
		for(int[] partition : splitProofPartitions){
			System.out.println(Partition.partitionToExpandedString(partition));
		}	
		System.out.println("Merge-proof:");
		for(int[] partition : mergeProofPartitions){
			System.out.println(Partition.partitionToExpandedString(partition));
		}		
		System.out.println("No-treat:");
		for(int[] partition : noTreatPartitions){
			System.out.println(Partition.partitionToExpandedString(partition));
		}					
		
		waitForUser();
	}
	
	public AltruismFromFile(String file){
		
		PartitionParser partitionParser = new PartitionParser(file);
		List<PartitionPlusExternalities> partitionPlusExtList = null;
		try{
		partitionPlusExtList = partitionParser.analyze();
		} catch(FileNotFoundException fnfe){
			System.out.println("can't find: " + file);
		}
		
		numAgents = partitionPlusExtList.get(0).getPartition().length;
		
		for(PartitionPlusExternalities ppe : partitionPlusExtList){
			System.out.println("Persisting partition: " + 
					coalition.formation.utils.Util.printIntArray(ppe.getPartition()));
			System.out.println("partition hash string: " +
					PartitionDecorator.convertToHashString(ppe.getPartition()) );
			System.out.println("externalities: " + 
					coalition.formation.utils.Util.printFloatArray(ppe.getExternalities() ) );
					
			externalities.put(
					PartitionDecorator.convertToHashString(ppe.getPartition()), 
					ppe.getExternalities());
		}
		
	}
	
	@Override
	public float[] getExternalities(int[] partition) {
		
		return externalities.get(PartitionDecorator.convertToHashString(partition));
		
	}

	@Override
	public int getSize() {
		return numAgents;
	}
	
	static void waitForUser(){
		String line = null;
		try {
			BufferedReader is = new BufferedReader(
					new InputStreamReader(System.in));
				line = is.readLine();
		} catch (IOException e) {
			System.err.println("Unexpected IO ERROR: " + e);
		}
	}

}
